package com.ytx.flutter_ytx_plugin.x5

import android.content.Context
import android.graphics.Bitmap
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.view.WindowManager.LayoutParams
import com.tencent.smtt.export.external.interfaces.IX5WebChromeClient
import com.tencent.smtt.export.external.interfaces.WebResourceRequest
import com.tencent.smtt.sdk.WebChromeClient
import com.tencent.smtt.sdk.WebView
import com.tencent.smtt.sdk.WebViewClient
import com.ytx.flutter_ytx_plugin.X5Request
import com.ytx.flutter_ytx_plugin.X5Response
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.platform.PlatformView


data class WebViewConfig(
    val useWideViewPort: Boolean = true,
    val javaScriptEnabled: Boolean = true,
    val domStorageEnabled: Boolean = true,
    val allowFileAccess: Boolean = true,
    val databaseEnabled: Boolean = true,
    val url: String = "",
    val header: Map<String, String> = mapOf(),
    val standardFullScreen: Boolean = false,
    val supportLiteWnd: Boolean = false,
    val defaultVideoScreen: Int = 2,
)


class X5WebView(
    private val context: Context,
    private val x5Response: X5Response,
    private val messenger: BinaryMessenger,
    private val params: Map<String, Any>,
    private val id: Int
) : PlatformView, X5Request {
    private var webView: WebView = WebView(context)
    val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    var fullView: View? = null

    init {
        X5Request.setUp(messenger, this)
        val config = WebViewConfig(
            useWideViewPort = params["useWideViewPort"] as? Boolean ?: true,
            javaScriptEnabled = params["javaScriptEnabled"] as? Boolean ?: true,
            domStorageEnabled = params["domStorageEnabled"] as? Boolean ?: true,
            allowFileAccess = params["allowFileAccess"] as? Boolean ?: true,
            databaseEnabled = params["databaseEnabled"] as? Boolean ?: true,
            header = params["header"] as? Map<String, String> ?: mapOf(),
            standardFullScreen = params["standardFullScreen"] as? Boolean ?: false,
            defaultVideoScreen = params["defaultVideoScreen"] as? Int ?: 2,
            url = params["url"] as? String ?: "",
        )

        webView.apply {
            settings.useWideViewPort = config.useWideViewPort
            settings.javaScriptEnabled = config.javaScriptEnabled
            settings.domStorageEnabled = config.domStorageEnabled
            settings.allowFileAccess = config.allowFileAccess
            settings.databaseEnabled = config.databaseEnabled
            settings.javaScriptCanOpenWindowsAutomatically = true

        }
        webView.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(
                view: WebView, request: WebResourceRequest?
            ): Boolean {
                if (request == null || request.url == null) {
                    throw Exception("Request or request URL is null.")
                } else {
                    handleUrlLoading(request.url.toString())
                }
                return true
            }

            override fun onPageStarted(p0: WebView?, p1: String?, p2: Bitmap?) {
                super.onPageStarted(p0, p1, p2)
                x5Response.onPageStarted(hashMapOf("url" to "$p1")) {}
            }

            override fun onPageFinished(view: WebView?, url: String) {
                x5Response.onPageFinished(hashMapOf("url" to url)) {}
            }
        }
        webView.webChromeClient = object : WebChromeClient() {
            override fun onShowCustomView(
                view: View?, callback: IX5WebChromeClient.CustomViewCallback?
            ) {
                handleShowCustomView(view, windowManager, fullView)
            }

            override fun onHideCustomView() {
                handleHideCustomView(fullView)
            }

            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                x5Response.onProgressChanged(hashMapOf("progress" to newProgress)) {}
            }
        }
        try {
            if (webView.x5WebViewExtension != null) {
                val data = Bundle()
                data.putBoolean("standardFullScreen", config.standardFullScreen)
                //true表示标准全屏，false表示X5全屏；不设置默认false，
                data.putBoolean("supportLiteWnd", config.supportLiteWnd)
                //false：关闭小窗；true：开启小窗；不设置默认true，
                data.putInt("DefaultVideoScreen", config.defaultVideoScreen)
                //1：以页面内开始播放，2：以全屏开始播放；不设置默认：1
                webView.x5WebViewExtension.invokeMiscMethod("setVideoParams", data)
            }
        } catch (ex: Exception) {
            ex.printStackTrace()
        }
        setupJavascriptChannels()


        if (config.url.isNullOrEmpty()) {
            throw Exception("Request or request URL is null.")
        }
        Log.d("X5WebView", ":$config.url")
        webView.loadUrl(config.url, config.header)
    }


    private fun setupJavascriptChannels() {
        val javascriptChannels = params["javascriptChannels"] as? List<String>
        javascriptChannels?.forEach { name ->
            webView.addJavascriptInterface(JavascriptChannel(name, callback = {
                x5Response.onJavascriptInterface(it) {}
            }, context), name)
        }
    }


    private fun handleUrlLoading(url: String) {
        x5Response.onUrlLoading(mapOf("key" to url)) {}
        webView.loadUrl(url)
    }

    private fun handleShowCustomView(view: View?, windowManager: WindowManager, fullView: View?) {
        if (view != null) {
            windowManager.addView(view, LayoutParams(LayoutParams.TYPE_APPLICATION))
            view.systemUiVisibility =
                (View.SYSTEM_UI_FLAG_LOW_PROFILE or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
            this.fullView = view
        }
        x5Response.onShowCustomView {
            print("x5web:onShowCustomView:${it.toString()}")
        }
    }

    private fun handleHideCustomView(fullView: View?) {
        if (fullView != null) {
            val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
            windowManager.removeView(fullView)
            this.fullView = null
        }
        x5Response.onHideCustomView {
            print("x5web:onHideCustomView:${it.toString()}")
        }
    }

    override fun getView(): View = webView

    override fun dispose() = webView.destroy()

    override fun initX5Sdk() = X5ApiHandler.setup(context, x5Response);

    override fun openVideo(map: Map<String, Any>) =
        X5ApiHandler.openVideo(context, x5Response, map);

    override fun openFile(map: Map<String, Any>) {}

    override fun openWebActivity(map: Map<String, Any>?) {}

    override fun setDownloadWithoutWifi(map: Map<String, Any>) {}

    override fun loadUrl(url: String, headers: Map<String, Any>?) =
        webView.loadUrl(url, headers?.get("headers") as? Map<String, String>)

    override fun reload() = webView.reload()

    override fun canGoBack(){
        webView.canGoBack()
    }

    override fun canGoForward(){
        webView.canGoForward()
    }

    override fun goBack() = webView.goBack()

    override fun goForward() = webView.goForward()

    override fun goBackOrForward(point: Long) = webView.goBackOrForward(point.toInt())

    override fun currentUrl(): String = webView.url

    override fun evaluateJavascript(map: Map<String, Any>) {
        val js = map["js"].toString()
        webView.evaluateJavascript(js) { }
    }

    override fun addJavascriptChannels(map: Map<String, Any>) {
        val names = map["names"] as List<String>
        for (name in names) {
            webView.addJavascriptInterface(JavascriptChannel(name, callback = {
                x5Response.onJavascriptInterface(it, {})
            }, context), name)
        }
        webView.reload()
    }

}